package jp.sourceforge.akjrcp.image.url2image;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.commons.ui.FileDirChoicer;
import jp.sourceforge.akjrcp.commons.ui.widget.WidgetBuilder;
import jp.sourceforge.akjrcp.ui.LayoutDataBuilder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.StatusTextEvent;
import org.eclipse.swt.browser.StatusTextListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;


public class URLToImageViewer extends ViewPart {
	public static Log log=LogFactory.getLog(URLToImageViewer.class);
	
	public static final String ID = URLToImageViewer.class.getName();

	private Browser browser;
	
	private Composite browserComposite;
	private Text addressText;
	private Text widthText;
	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	private int scrollBarPlusWidth=17;
	//private int offseBordert=1;
	private int defaultWidth=640;
	private int picturewidth=defaultWidth;
	private int windowHeight;

	private FileDirChoicer exportPath;

	private Button captureButton;
	private int marginTop;
	private int marginLeft;
	private int marginRight;
	private int marginBottom;
	private final int edgeData[][]=toEdgeData();

	public static final int SCROLL_MARGIN=17;
	private int scrollBarPlusHeight=17;

	protected int windowWidth;

	private boolean debug=false;	//save png per frame.
	
	
	public void openURL(String url){
		captureButton.setEnabled(false);
		browser.setUrl(url);
		
	}
	public static int[][] toEdgeData(){
		int check[][]=new int[4][4];
		check[0][0]=-1716999168;
		check[1][0]=-1716999168;
		check[2][0]=-1716999168;
		check[3][0]=-1716999168;
		check[0][1]=-1716999168;
		check[1][1]=1685025024;
		check[2][1]=1685025024;
		check[3][1]=1685025024;
		check[0][2]=-1716999168;
		check[1][2]=1685025024;
		//check[2][2]=-256;
		//check[3][2]=-256;
		check[0][3]=-1716999168;
		check[1][3]=1685025024;
		//check[2][3]=-256;
		//check[3][3]=-256; no need
		return check;
	}
	public void widthChange(){
		int change=defaultWidth;
		try{
			change=Integer.parseInt(widthText.getText());
		}catch(Exception e){}
		widthText.setText(""+change);
		browser.setLayoutData(LayoutDataBuilder.hintGridData(change+scrollBarPlusWidth+marginLeft+marginRight, -1));//TODO resize check
		browser.getParent().layout();
		picturewidth=change;
		
		int size=PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getSize().x;
		log.trace(size);
		int marginShellSize=58;
		//how to resize shell window
		if(size<change+marginShellSize){
			PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setSize(change+marginShellSize, PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getSize().y);
		}
		
		//re check
		browser.execute("window.status=\"HEIGHT=\"+document.body.scrollHeight");//
		browser.execute("window.status=\"WIDTH=\"+document.body.scrollWidth");//
	}
	
	public boolean hasEdge(Composite composite){
		GC gc = new GC(composite);
		
		final Image image =
			new Image(PlatformUI.getWorkbench().getDisplay(), 4,4);
		
		
		gc.copyArea(image, 0, 0);
		gc.dispose();
		for(int i=0;i<4;i++){
			for(int j=0;j<4;j++){
				if(j>=2&&i>=2){
					
				}else{
				if(image.getImageData().getPixel(j, i)!=edgeData[j][i]){
					return false;
				}
				}
				//log.trace(i+"x"+j+"="+Integer.toHexString(image.getImageData().getPixel(j, i)));
				//log.trace("check["+j+"]["+i+"]="+image.getImageData().getPixel(j, i)+";");
			}
		}
		return true;
	}
	
	
	public Image browserToImage(Composite composite){
		GC gc = new GC(composite);
		
		final Image image =
			new Image(PlatformUI.getWorkbench().getDisplay(), composite.getSize().x-scrollBarPlusWidth-marginLeft,composite.getSize().y-scrollBarPlusHeight-marginTop);
		
		
		gc.copyArea(image, marginLeft, marginTop);
		gc.dispose();
		//image.getImageData().setPixel(0, image.getBounds().height-1, 0xff0000);
		return image;
	}
	
	public Image compositeToImage(Composite composite){
		GC gc = new GC(composite);
		
		final Image image =
			new Image(PlatformUI.getWorkbench().getDisplay(), composite.getSize().x,composite.getSize().y);
		gc.copyArea(image, 0, 0);
		gc.dispose();
		return image;
	}
	
	public void scrollY(int x,int y){
		browser.execute("window.scrollTo("+x+","+y+")");
	}
	
	private void savePNGImage(Image img,String filePath){
		ImageLoader loader=new ImageLoader();
		loader.data=new ImageData[]{img.getImageData()};
		loader.save(filePath, SWT.IMAGE_PNG);
	}
	public void createPartControl(Composite parent) {
		parent.setLayout(new GridLayout());
		Composite controlPanel=new Composite(parent,SWT.NULL);
		controlPanel.setLayout(new GridLayout(4,false));
		controlPanel.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		captureButton = new Button(controlPanel,SWT.NULL);
		captureButton.setText("capture");
		captureButton.setEnabled(false);
		captureButton.addSelectionListener(new SelectionListener(){
			
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			public void widgetSelected(SelectionEvent e) {
				createPicture();
			}
		}
			);
		WidgetBuilder.createLabel(controlPanel, Messages.getString("url2image.width"));
		widthText=WidgetBuilder.createBorderText(controlPanel, ""+defaultWidth);
		widthText.setLayoutData(LayoutDataBuilder.hintGridData(40, 0));
		widthText.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
				widthChange();
			}

			public void widgetSelected(SelectionEvent e) {
				
			}
			
		});
		
		exportPath = new FileDirChoicer(controlPanel,SWT.NULL,FileDirChoicer.FILE,Messages.getString("url2image.exportPath"));
		exportPath.setFilterExtensions(new String[]{"*.png"});
		exportPath.setFilePath(System.getProperty("user.dir")+"\\"+"capture.png");
		addressText=WidgetBuilder.createBorderText(parent, "http://wikipedia.jp");
		addressText.setLayoutData(LayoutDataBuilder.fillHorizontalGridData());
		addressText.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
				openURL(addressText.getText());
			}

			public void widgetSelected(SelectionEvent e) {
				
			}
			
		});
		
		
		Composite panel=new Composite(parent,SWT.NULL);
		panel.setLayout(new GridLayout(2,false));
		panel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		Button back=new Button(panel,SWT.NULL);
		back.setText(Messages.getString("youtubeview.back"));
		back.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
			}

			public void widgetSelected(SelectionEvent e) {
				browser.back();
			}
			
		});
		
		Button forward=new Button(panel,SWT.NULL);
		forward.setText(Messages.getString("youtubeview.foward"));
		forward.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {
			}

			public void widgetSelected(SelectionEvent e) {
				browser.forward();
			}
			
		});
		
		//parent.setLayout(new FillLayout());
		browserComposite=new Composite(parent,SWT.NULL);
		browserComposite.setLayoutData(LayoutDataBuilder.hintGridData(-1, -1));
		browserComposite.setLayout(new GridLayout(1,false));
		
		browser = new Browser(browserComposite,SWT.NULL);
		browser.setUrl(addressText.getText());
		browser.setLayoutData(LayoutDataBuilder.hintGridData(defaultWidth+scrollBarPlusWidth+marginLeft, -1));
		//browser.setUrl("http://www.youtube.com");
		browser.addLocationListener(new LocationListener(){

			public void changed(LocationEvent event) {
				log.trace(browser.getSize());
				log.trace(browser.getClientArea());
				captureButton.setEnabled(true);
				
				//browser.execute("alert(document.getElementsByTagName(\"body\")[0].style.marginTop)");
				//browser.execute("window.status=\"HEIGHT=\"+document.documentElement.scrollHeight;");
				browser.execute("window.status=\"HEIGHT=\"+document.body.scrollHeight");//
				browser.execute("window.status=\"WIDTH=\"+document.body.scrollWidth");//
				//browser.execute("window.resizeTo("+windowWidth+", 480)");
				/*
				String url=event.location;
				
				//if(YoutubeUtils.isYoutubeVideoURL(url)){
					YoutubeDLView view=(YoutubeDLView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(YoutubeDLView.ID);
					if(view!=null){
						view.setUrl(url);
					}
					*/
				//}
				/*
				ImageCapture capture=new ImageCapture();
				
				
				log.infochanged:"+event.location);
				GC gc = new GC(browser);
				final Image image =
					new Image(PlatformUI.getWorkbench().getDisplay(), browser.getSize().x,browser.getSize().y);
				gc.copyArea(image, 0, 0);
				gc.dispose();
				
				//Image image=capture.getImage(browser,true);
				ImageLoader loader=new ImageLoader();
				loader.data=new ImageData[]{image.getImageData()};
				loader.save("c:\\tmp\\t2.jpg", SWT.IMAGE_JPEG);
				*/
				//loader
				/*
				try {
					//only in screen
					Robot robot = new Robot();
					BufferedImage img=robot.createScreenCapture(new Rectangle(0,720,320,1000));
					try {
						ImageIO.write(img, "jpg", new File("c:\\tmp\\t.jpg"));
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (AWTException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}*/
			}

			public void changing(LocationEvent event) {
				//changing much faster
				String url=event.location;
				//browser.execute("window.status=\"HEIGHT=\"+document.documentElement.scrollHeight;");
			}});
		
		/*
		browser.addOpenWindowListener(new OpenWindowListener(){

			public void open(WindowEvent event) {
				log.trace(event);
			}
			
		});
		
		browser.addVisibilityWindowListener(new VisibilityWindowListener(){

			public void hide(WindowEvent event) {
				// TODO Auto-generated method stub
				
			}

			public void show(WindowEvent event) {
				log.trace(event);
			}});
	*/
		browser.addStatusTextListener(new StatusTextListener() {
		    public void changed(StatusTextEvent e) {
		        // JavaScript�Őݒ肵���l��\������
		       // log.trace("window.status=" + e.text);
		        int value=0;
		        if(e.text.startsWith("HEIGHT=")){
		        	
		        
		        try{
		        value=Integer.parseInt(e.text.substring("HEIGHT=".length()));
		        }catch(Exception e2){};
		        if(value>0){
		       // int location= value-browser.getSize().y;
		        //log.trace("height:"+value);
		        windowHeight=value;
		       // browser.getChildren()[0].setLocation(0,-100);//scroll full?
		        //browser.layout();
		        }
		        }
		        
		        if(e.text.startsWith("WIDTH=")){
		        	
			        
			        try{
			        value=Integer.parseInt(e.text.substring("WIDTH=".length()));
			        }catch(Exception e2){};
			        if(value>0){
			       // int location= value-browser.getSize().y;
			        //log.trace("height:"+value);
			        windowWidth=value;
			      //  log.trace("windowWidth:"+windowWidth);
			       // browser.getChildren()[0].setLocation(0,-100);//scroll full?
			        //browser.layout();
			        }
			        }
		    }
		});
		
	}
	
	public void setFocus() {
		
	}
	
	

	
	public void debugArray(String[] array){
		String v="";
		for (int i = 0; i < array.length; i++) {
			v+="\""+array[i]+"\""+" ";
		}
		log.info(v);
		Akj_betasPlugin.getDefault().getProcessPrinter().printOutput(v+"\n");
	}
	private void createPicture() {
		scrollY(0, 0);
		captureButton.setEnabled(false);
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//wait back;
		if(hasEdge(browser)){
			marginLeft=2;
			marginTop=2;
			marginRight=4;//TODO change 1;
			log.trace("hasEdge");
		}else{
			marginLeft=0;
			marginTop=0;
			marginRight=0;
		}
		widthChange();//for edge fix;
		
		if(windowWidth<=browser.getSize().x-SCROLL_MARGIN-4){
			scrollBarPlusHeight=1;//
		}
		log.trace("scrollBarPlusHeight:"+scrollBarPlusHeight);
		//log.trace("v:"+browser.getParent().getVerticalBar());
		Point browserSize=browser.getSize();
		
		
		
		int outSideArea=scrollBarPlusHeight+marginTop*2; //scroll+insect

		//currentView
		
		int captureArea=(browserSize.y-outSideArea);
		
		
		
		
		final Image image =
			new Image(PlatformUI.getWorkbench().getDisplay(), picturewidth,windowHeight-marginTop*2);
		GC gc=new GC(image);
		
		int nums=windowHeight/captureArea; 
		//nums=2;//debug;
		int mod=windowHeight%captureArea;
		int current=0;
		for(int i=0;i<nums;i++){
			final Image tmpImage =browserToImage(browser);
			gc.drawImage(tmpImage, 0, current);
			
			int minus=0;
			if(marginTop>0){
				//minus=marginTop;
			}
			current+=captureArea-minus;// i don know? need 1?
			if(debug)
				savePNGImage(compositeToImage(browser),"c:\\tmp\\browser"+i+".png"); //for debug
			scrollY(0, (i+1)*captureArea-minus);
		}
		
		if(mod>0){
			current-=(captureArea-mod);
			current+=marginTop;
			if(scrollBarPlusHeight!=1){//has scroll
				//current+=marginTop;
				}
			else{//no scroll
				current+=marginTop;
			}
			final Image tmpImage =browserToImage(browser);
			gc.drawImage(tmpImage, 0, current);
			if(debug)
				savePNGImage(compositeToImage(browser),"c:\\tmp\\browser"+99+".png"); //for debug
		}
		
		
		
//				Image image=capture.getImage(browser,true);
		
			savePNGImage(image,exportPath.getAbsoluteFilePath());
		scrollY(0,0);
		captureButton.setEnabled(true);
		
	}
	
	
	
	
		
}